package edu.hawaii.myisern.action;

import edu.hawaii.myisern.model.ListStringConverter;
import edu.hawaii.myisern.model.MyIsernModel;
import java.util.List;
import edu.hawaii.myisern.organizations.jaxb.AffiliatedResearchers;
import edu.hawaii.myisern.organizations.jaxb.Organization;
import edu.hawaii.myisern.organizations.jaxb.ResearchKeywords;
//import edu.hawaii.myisern.researchers.jaxb.Researcher;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.RedirectResolution;
import net.sourceforge.stripes.action.Resolution;


/**
 * Allows for a organization to be added or edited. 
 * 
 * @author Ed Kim
 * @author Jon Lao
 * @author JianFei Liao
 * @author Jared Sunouchi
 */
public class OrganizationActionBean implements ActionBean {
  /** Required by the ActionBean interface. */
  private ActionBeanContext context;
  /** An error string, always displayed, but invisible if empty. */
  private String errorMessage = "";
  /** Added? */
  private boolean added;
  /** Editing? */
  private boolean editing;
  /** Edited? */
  private boolean edited;
  /** The single MyIsern instance manipulated by all webapp users. */
  private MyIsernModel myIsern = MyIsernModel.getInstance();
  /** Researcher attributes */
  private String name;
  private String type;
  private String contact;
  private String affiliatedResearchers;
  private String country;
  private String researchKeywords;
  private String researchDescription;
  private String homePage;

  private String organizationNamesList;
  private String researcherNamesList;
  private static final String ADD_ORG_PAGE = "/addOrganization.jsp";
  private static final String EDIT_ORG_PAGE = "/editOrganization.jsp";
  private static final String EMPTY_STRING = "";
  private static final String HOME_PAGE = "/home.jsp";
  
  /** A converter between list and objects. */
  private ListStringConverter converter = new ListStringConverter();
  
  /** Variable from jsp pages used to find organization */
  private String linkItem = " ";
  
  /**
   * Returns the context. Required by the interface. 
   * 
   * @return the ActionBeanContext.
   */
  public ActionBeanContext getContext() {
    return context;
  }
  
  /**
   * Sets the context. Required by the interface. 
   * 
   * @param context The ActionBeanContext to set. 
   */
  public void setContext(ActionBeanContext context) {
    this.context = context;
  }
  
  /**
   * Returns the error message, which may be empty.
   * Indicates if an error was made adding or editing the organization. 
   * 
   * @return The error message. 
   */
  public String getErrorMessage() {
    return this.errorMessage;
  }
  
  /**
   * Returns the whether the organization has been added or not.
   * 
   * @return Whether the organization has been added or not. 
   */
  public boolean getAdded() {
    return this.added;
  }
  
  /**
   * Returns the whether the organization has been edited or not.
   * 
   * @return Whether the organization has been edited or not. 
   */
  public boolean getEdited() {
    return this.edited;
  }
  
  /**
   * Returns the whether the organization is being edited or not.
   * 
   * @return Whether the organization is being edited or not. 
   */
  public boolean getEditing() {
    return this.editing;
  }
  
  /**
   * Returns the string representation that will be used to generate the javascript array.
   * 
   * @return The string representation that will be used to generate the javascript array. 
   */
  public String getOrganizationNamesList() {
    this.organizationNamesList = myIsern.getOrganizationNamesList();
    return this.organizationNamesList;
  }
  
  /**
   * Returns the string representation that will be used to generate the javascript array.
   * 
   * @return The string representation that will be used to generate the javascript array. 
   */
  public String getResearcherNamesList() {
    this.researcherNamesList = myIsern.getResearcherNamesList();
    return this.researcherNamesList;
  }
  
//  /**
//   * Displays the form to add a organization.
//   * 
//   * @return A Resolution indicating to redisplay the add.jsp page.
//   */
//  public Resolution organizationForm() {
//    return new ForwardResolution(ADD_ORG_PAGE);
//  }
  
  /**
   * Displays the form to edit an organization.
   * 
   * @return A Resolution indicating to redisplay the edit.jsp page.
   */
  public Resolution editOrganizationForm() {
    return new ForwardResolution(EDIT_ORG_PAGE);
  }
  
  /**
   * Resets the organization data.
   */
  public void resetData() {
    this.setName("");
    this.setType("");
    this.setContact("");
    this.setAffiliatedResearchers("");
    this.setCountry("");
    this.setResearchKeywords("");
    this.setResearchDescription("");
    this.setHomePage("");
  }
  
  /**
   * Clears the text in the text boxes.
   * 
   * @return A Resolution indicating to redirect to the add.jsp page.
   */
  public Resolution reset() {
    this.resetData();
    return new RedirectResolution(ADD_ORG_PAGE).flash(this);
  }
  
  /**
   * Clears the text in the text boxes.
   * 
   * @return A Resolution indicating to redirect to the home.jsp page.
   */
  public Resolution cancel() {
    return new RedirectResolution(HOME_PAGE);
  }
  
  /**
   * Sets the name of the organization.
   * 
   * @param name The name to set.
   */
  public void setName(String name) {
    this.name = name.trim();
  }
  
  /**
   * Returns the name of the organization.
   * @return The name of the organization.
   */
  public String getName() {
    return this.name;
  }
  
  /**
   * Sets the type of the organization.
   * 
   * @param type The type to set.
   */
  public void setType(String type) {
    this.type = type.trim();
  }
  
  /**
   * Returns the type of the organization.
   * @return The type of the organization.
   */
  public String getType() {
    return this.type;
  }
  
  /**
   * Sets the contact of the organization.
   * 
   * @param contact The contact to set.
   */
  public void setContact(String contact) {
    this.contact = contact.trim();
  }
  
  /**
   * Returns the contact of the organization.
   * 
   * @return The contact of the organization.
   */
  public String getContact() {
    return this.contact;
  }
  
  /**
   * Sets the affiliated researchers of the organization.
   * 
   * @param affiliatedResearchers  The researchers to set.
   */
  public void setAffiliatedResearchers(String affiliatedResearchers) {
    this.affiliatedResearchers = affiliatedResearchers;
  }
  
  /**
   * Returns the affiliated researchers of the organization.
   * 
   * @return The affiliated researchers of the organization.
   */
  public String getAffiliatedResearchers() {
    return this.affiliatedResearchers;
  }
  
  /**
   * Sets the country of the organization.
   * 
   * @param country The country to set.
   */
  public void setCountry(String country) {
    this.country = country.trim();
  }
  
  /**
   * Returns the country of the organization.
   * 
   * @return The country of the organization.
   */
  public String getCountry() {
    return this.country;
  }
  
  /**
   * Sets the research keywords of the organization.
   * 
   * @param researchKeywords  The keywords to set.
   */
  public void setResearchKeywords(String researchKeywords) {
    this.researchKeywords = researchKeywords;
  }
  
  /**
   * Returns the research keywords of the organization.
   * 
   * @return The research keywords of the organization.
   */
  public String getResearchKeywords() {
    return this.researchKeywords;
  }
  
  /**
   * Sets the research description of the organization.
   * 
   * @param researchDescription The research description to set.
   */
  public void setResearchDescription(String researchDescription) {
    this.researchDescription = researchDescription.trim();
  }
  
  /**
   * Returns the research description of the organization.
   * 
   * @return The research description of the organization.
   */
  public String getResearchDescription() {
    return this.researchDescription;
  }
  
  /**
   * Sets the home page of the organization.
   * 
   * @param homePage The home page to set.
   */
  public void setHomePage(String homePage) {
    this.homePage = homePage.trim();
  }
  
  /**
   * Returns the home page of the organization.
   * 
   * @return The home page of the organization.
   */
  public String getHomePage() {
    return this.homePage;
  }
  
  /**
   * Adds a organization.
   * 
   * @return A Resolution indicating to redisplay the add.jsp page.
   * @throws Exception If problems occur.
   */
  public Resolution add() throws Exception {
    if ((this.name == null) || ("".equals(this.name))) {
      this.errorMessage = "Please enter a name.";
    }
    else {
      List<Organization> list = myIsern.getOrganizationsList();
      boolean found = false;
      for (Organization organization : list) {
        if (organization.getName().equals(this.name.replace('_', ' '))) {
          found = true;
        }
      }
      
      if (found) {
        this.errorMessage = "Organization already exists. Please edit instead.";
        this.editing = true;
        Organization org = this.myIsern.getSingleOrganization(this.name);
        this.type = org.getType();
        this.contact = org.getContact();
        this.affiliatedResearchers = this.converter.listToString(org
            .getAffiliatedResearchers().getAffiliatedResearcher());
        this.country = org.getCountry();
        this.researchKeywords = this.converter.listToString(org.getResearchKeywords()
            .getResearchKeyword());
        this.researchDescription = org.getResearchDescription();
        this.homePage = org.getHomePage();
        return new RedirectResolution(EDIT_ORG_PAGE).flash(this);
      }
      else {
        Organization newOrganization = new Organization();
        newOrganization.setName(this.name);
        if (this.type == null) {
          newOrganization.setType(EMPTY_STRING);
        }
        else {
          newOrganization.setType(this.type);
        }
        if (this.contact == null) {
          newOrganization.setContact(EMPTY_STRING);
        }
        else {
          newOrganization.setContact(this.contact);
        }
        AffiliatedResearchers newAffiliatedResearchers = new AffiliatedResearchers();
        newAffiliatedResearchers.getAffiliatedResearcher()
            .addAll(this.converter.stringToList((this.affiliatedResearchers)));
        newOrganization.setAffiliatedResearchers(newAffiliatedResearchers);
        if (this.country == null) { 
          newOrganization.setCountry(EMPTY_STRING);
        }
        else {
          newOrganization.setCountry(this.country);
        }
        if (this.researchKeywords == null) {
          this.errorMessage = "At least one researcher keyword is required.";
          return this.getContext().getSourcePageResolution();
        }
        else {
          ResearchKeywords newResearchKeywords = new ResearchKeywords();
          newResearchKeywords.getResearchKeyword()
              .addAll(this.converter.stringToList(this.researchKeywords));
          newOrganization.setResearchKeywords(newResearchKeywords);
        }
        if (this.researchDescription == null) {
          newOrganization.setResearchDescription(EMPTY_STRING);
        }
        else {
          newOrganization.setResearchDescription(this.researchDescription);
        }
        if (this.homePage == null) {
          newOrganization.setHomePage(EMPTY_STRING);
        }
        else {
          newOrganization.setHomePage(this.homePage);
        }
        
        myIsern.addOrEditOrganization(newOrganization);
        
        this.added = true;
      }
    }
    return new ForwardResolution(ADD_ORG_PAGE);
  }
  
  /**
   * Displays the information to edit.
   * 
   * @return A resolution indicating to redisplay the edit.jsp page.
   * @throws Exception If problems occur.
   */
  public Resolution displayEdit() throws Exception {
    List<Organization> list = myIsern.getOrganizationsList();
    Organization editOrganization = new Organization();
    boolean found = false;
    for (Organization organization : list) {
      if (organization.getName().equals(this.name.replace('_', ' '))) {
        editOrganization = organization;
        found = true;
      }
    }

    if (found) {
      this.type = editOrganization.getType();
      this.contact = editOrganization.getContact();
      this.affiliatedResearchers = this.converter.listToString(editOrganization
          .getAffiliatedResearchers().getAffiliatedResearcher());
      this.country = editOrganization.getCountry();
      this.researchKeywords = this.converter.listToString(editOrganization.getResearchKeywords()
          .getResearchKeyword());
      this.researchDescription = editOrganization.getResearchDescription();
      this.homePage = editOrganization.getHomePage();

      this.editing = true;
    }
    return new ForwardResolution(EDIT_ORG_PAGE);
  }
  
  /**
   * Edits a organization.
   * 
   * @return A resolution indicating to redisplay the edit.jsp page.
   * @throws Exception If problems occur.
   */
  public Resolution edit() throws Exception {
    List<Organization> list = myIsern.getOrganizationsList();
    Organization editOrganization = new Organization();
    for (Organization organization : list) {
      if (organization.getName().equals(this.name.replace('_', ' '))) {
        editOrganization = organization;
      }
    }
    if (this.type == null) {
      editOrganization.setType(EMPTY_STRING);
    }
    else {
      editOrganization.setType(this.type);
    }
    if (this.contact == null) {
      editOrganization.setContact(EMPTY_STRING);
    }
    else {
      editOrganization.setContact(this.contact);
    }
    AffiliatedResearchers newAffiliatedResearchers = new AffiliatedResearchers();
    newAffiliatedResearchers.getAffiliatedResearcher()
        .addAll(this.converter.stringToList((this.affiliatedResearchers)));
    editOrganization.setAffiliatedResearchers(newAffiliatedResearchers);
    if (this.country == null) { 
      editOrganization.setCountry(EMPTY_STRING);
    }
    else {
      editOrganization.setCountry(this.country);
    }
    if (this.researchKeywords == null) {
      this.errorMessage = "At least one researcher keyword is required.";
      this.editing = true;
      return this.getContext().getSourcePageResolution();
    }
    else {
      ResearchKeywords newResearchKeywords = new ResearchKeywords();
      newResearchKeywords.getResearchKeyword()
          .addAll(this.converter.stringToList(this.researchKeywords));
      editOrganization.setResearchKeywords(newResearchKeywords);
    }
    if (this.researchDescription == null) {
      editOrganization.setResearchDescription(EMPTY_STRING);
    }
    else {
      editOrganization.setResearchDescription(this.researchDescription);
    }
    if (this.homePage == null) {
      editOrganization.setHomePage(EMPTY_STRING);
    }
    else {
      editOrganization.setHomePage(this.homePage);
    }
    
    myIsern.addOrEditOrganization(editOrganization);
    
    this.edited = true;
    this.editing = true; 
    return new ForwardResolution(EDIT_ORG_PAGE);
  }
  
  /**
   * Removes the organization.
   * 
   * @return A resolution indicating to redisplay the add.jsp or edit.jsp page.
   * @throws Exception If problems occur.
   */
  public Resolution remove() throws Exception {    
    myIsern.removeOrganization(this.name);
    
    this.errorMessage = this.name + " has been removed.";
    return new ForwardResolution(ADD_ORG_PAGE);
  }
  
  /**
   * Sets the link item variable from jsp pages.
   * 
   * @param string The new invalid organization link.
   */
  public void setLinkItem(String string) {
    this.linkItem = string;
  }
  
  /**
   * Finds the organization by name from jsp link item variable.
   * Redirects to Add organization if it doesn't exist or
   * Edit organization if it does.
   * 
   * @return resolution either to editing or adding the organization.
   */
  public Resolution linkToOrganization() {
   Organization o = this.myIsern.getSingleOrganization(this.linkItem);
   if (o == null) {
     this.name = this.linkItem;
     this.added = false;
     return new RedirectResolution(ADD_ORG_PAGE).flash(this);
   }
   else {
     this.name = this.linkItem;
     this.type = o.getType();
     this.contact = o.getContact();
     
     this.affiliatedResearchers = 
       this.converter.listToString(o.getAffiliatedResearchers().getAffiliatedResearcher());
     
     this.country = o.getCountry();
     
     this.researchKeywords = 
       this.converter.listToString(o.getResearchKeywords().getResearchKeyword());
     
     this.researchDescription = o.getResearchDescription();
     this.homePage = o.getHomePage();
     
     this.edited = false;
     this.editing = true;
     return new RedirectResolution(EDIT_ORG_PAGE).flash(this);
   }
 }  
}
